package com.ruoyi.system.utils;

import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.domain.dto.SysUserLoginDTO;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@Service
public class SignatureVerificationService {

    @Autowired
    private SysUserMapper sysUserInfoMapper;

    /**
     * 验证前端签名
     * @param clientSignature 前端传来的SHA-1签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param appKey 用户ID
     * @return 验证结果
     */
    public boolean verifySignature(String clientSignature, long timestamp,
                                   long nonce, String appKey) {

        try {
            // 1. 从数据库获取用户信息
            SysUserLoginDTO user = sysUserInfoMapper.getByLg(appKey);
            if (user == null) {
                return false;
            }
            System.out.println("user: " + user);
            // 2. 解密存储在数据库中的密码
            String decryptedPassword = SecurityUtils.decryptPassword(user.getPassword());
            System.out.println("decryptedPassword: " + decryptedPassword);

            // 3. 使用解密后的密码重新计算SHA-1签名
            String serverSignature = calculateSHA1(decryptedPassword, timestamp, nonce);
            System.out.println("serverSignature: " + serverSignature);

            // 4. 比较两个签名是否一致
            return serverSignature.equals(clientSignature);

        } catch (Exception e) {
            throw new RuntimeException("签名验证失败: " + e.getMessage(), e);
        }
    }

    /**
     * SHA-1计算方法（必须与前端完全一致）
     */
    private String calculateSHA1(String data, long timestamp, long nonce) {
        try {
            // 注意：拼接顺序必须与前端完全一致
            String str = data + timestamp + nonce;

            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.getBytes(StandardCharsets.UTF_8));
            byte[] hashBytes = digest.digest();

            return bytesToHex(hashBytes);
        } catch (Exception e) {
            throw new RuntimeException("SHA-1计算失败", e);
        }
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    /**
     * 增强版验证：包含时间戳验证和防重放攻击
     */
    public boolean verifySignatureEnhanced(String clientSignature, long timestamp,
                                                      long nonce, String appKey) {

        System.out.println("timestamp: " + timestamp+" nonce: " + nonce+" appKey: " + appKey+" clientSignature: " + clientSignature);
        // 1. 验证时间戳有效性
        if (!isTimestampValid(timestamp)) {
            System.out.println("时间戳无效");
//            return new VerificationResult(false, "时间戳无效");
            return false;
        }

        // 2. 验证签名
        boolean signatureValid = verifySignature(clientSignature, timestamp, nonce, appKey);

        if (signatureValid) {
//            return new VerificationResult(true, "验证成功");
            return true;
        } else {
//            return new VerificationResult(false, "签名不匹配");
            return false;
        }
    }

    public boolean isTimestampValid(long timestampMillis) {
        long currentTimeMillis = System.currentTimeMillis();
        long timeDiff = Math.abs(currentTimeMillis - timestampMillis);
        return timeDiff <= 5 * 60 * 1000;
    }

    public static class VerificationResult {
        private final boolean success;
        private final String message;

        public VerificationResult(boolean success, String message) {
            this.success = success;
            this.message = message;
        }

        // getter方法
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
    }
}